<?php

/**
 * Fasade class for the price modules
 *
 * @access 	public
 * @author 	Rob
 * @copyright	ResMania 2009 all rights reserved.
 * @version	1.0
 * @link		http://developer.resmania.com/api
 * @since  	05-2009
 */
class RM_Module_ExcursionPrices extends RM_Module implements RM_Search_Advanced_Interface, RM_Prices_Interface, RM_Unit_Copy_Interface {

    public function __construct() {
        $this->name = 'ExcursionPrices';
    }

    /**
     * copys the unit price information used by the copy unit function
     *
     * @param RM_Unit_Row $original
     * @param RM_Unit_Row $copy
     */
    function copyInformation(RM_Unit_Row $original, RM_Unit_Row $copy) {
        $unitPricesModel = new RM_UnitExcursionPrices();
        $unitPrices = $unitPricesModel->getByUnit($original);
        foreach ($unitPrices as $unitPrice) {
            $unitPriceCopyData = $unitPrice->toArray();
            unset($unitPriceCopyData['id']);
            $unitPriceCopyData['unit_id'] = $copy->id;
            $unitPriceCopy = $unitPricesModel->createRow($unitPriceCopyData);
            $unitPriceCopy->save();
        }

        $unitPricesConfigModel = new RM_UnitExcursionPricesConfig();
        $unitPricesConfigs = $unitPricesConfigModel->getByUnit($original);
        foreach ($unitPricesConfigs as $unitPricesConfig) {
            $unitPricesConfigCopyData = $unitPricesConfig->toArray();
            $unitPricesConfigCopyData['unit_id'] = $copy->id;
            $unitPricesConfigCopy = $unitPricesConfigModel->createRow($unitPricesConfigCopyData);
            $unitPricesConfigCopy->save();
        }
    }

    /**
     * Returns all unit ids that are passed criteria option
     *
     * @param RM_Unit_Search_Criteria $criteria
     * @return array, false
     */
    function getAdvancedSearchUnitIDs(RM_Unit_Search_Criteria $criteria) {
        if (!$criteria->adults || count($criteria->adults) == 0)
            return false;

        $unitIDs = array();
        $model = new RM_UnitExcursionPricesConfig();
        $personsConfigs = $model->getAll()->toArray();

        $totalPersons = (int) $criteria->adults + (int) $criteria->children + (int) $criteria->infants;

        foreach ($personsConfigs as $configItem) {

            $unitConfig[(int)$configItem['unit_id']][$configItem['name']] = (int)$configItem['value'];

        }

        // if the passed unit is not using Excursion prices the $unitConfig value will be empty for these.
        // so we can safely exit returning false as it's not used.
        if (isset($unitConfig)){
            foreach ($unitConfig as $unid_id => $information) {
                if ($totalPersons <= $information['max_occupancy']) {

                    if (
                            $criteria->adults <= $information['max_adults']
                            &&
                            $criteria->children <= $information['max_children']
                            &&
                            $criteria->infants <= $information['max_infants']
                    ) {
                        $unitIDs[] = $unid_id;
                    }
                }
            }
        } else {
            return false;
        }

        //we need to add code to support Group Module
        //we need to include every unit ID of a groups that main unit in group assigned to a category
        if (class_exists('RM_Groups')) {
            $groupUnitIDs = array();
            $groupsModel = new RM_Groups();
            $unitsModel = new RM_Units();
            foreach ($unitIDs as $unitID) {
                $unit = $unitsModel->get($unitID);
                if ($groupsModel->isMain($unit)) {
                    $units = $groupsModel->getGroupUnitsByMain($unit);
                    foreach ($units as $unit) {
                        $groupUnitIDs[] = $unit->getId();
                    }
                }
            }
            $unitIDs = array_merge($unitIDs, $groupUnitIDs);
            $unitIDs = array_unique($unitIDs);
        }

        if (count($unitIDs)===0) return false;
        return $unitIDs;
    }

    /**
     * Upgrade routine
     */
    public function upgrade(){
        $rootPath = RM_Environment::getConnector()->getRootPath();
        $pluginFolderPath = implode(DIRECTORY_SEPARATOR, array(
                    $rootPath,
                    'RM',
                    'userdata',
                    'modules',
                    $this->name,
                    'views',
                    'user',
                    'scripts',
                    'Search',
                    'advanced',
                    'excursion_persons_advancedsearch.phtml'
                ));
        $userdataFolderPath = implode(DIRECTORY_SEPARATOR, array(
                    $rootPath,
                    'RM',
                    'userdata',
                    'views',
                    'user',
                    'scripts',
                    'Search',
                    'advanced',
                    'excursion_persons_advancedsearch.phtml'
                ));
        return rename($pluginFolderPath, $userdataFolderPath);
    }

    public function install() {
        parent::install();

        //1. move template for advanced search panel
        //the standard algorithm already moves userdata/view templates into plugin separate direstory thats why we need to move this file into main template directory
        $rootPath = RM_Environment::getConnector()->getRootPath();
        $pluginFolderPath = implode(DIRECTORY_SEPARATOR, array(
                    $rootPath,
                    'RM',
                    'userdata',
                    'modules',
                    $this->name,
                    'views',
                    'user',
                    'scripts',
                    'Search',
                    'advanced',
                    'excursion_persons_advancedsearch.phtml'
                ));
        $userdataFolderPath = implode(DIRECTORY_SEPARATOR, array(
                    $rootPath,
                    'RM',
                    'userdata',
                    'views',
                    'user',
                    'scripts',
                    'Search',
                    'advanced',
                    'excursion_persons_advancedsearch.phtml'
                ));
        return rename($pluginFolderPath, $userdataFolderPath);
    }

    public function uninstall() {
        parent::uninstall();

        //1. remove template for advanced search panel
        $rootPath = RM_Environment::getConnector()->getRootPath();
        $file = implode(DIRECTORY_SEPARATOR, array(
                    $rootPath,
                    'RM',
                    'userdata',
                    'views',
                    'user',
                    'scripts',
                    'Search',
                    'advanced',
                    'excursion_persons_advancedsearch'
                ));
        RM_Filesystem::deleteFile($file);

        //2. remove information about this panel from database in form->state field
        $formModel = new RM_Forms();
        $form = $formModel->find('advancedsearch')->current();
        $deleted = $form->deletePanel('excursion_persons_advancedsearch');
        if ($deleted) {
            $form->save();
        }
    }

    public function getNode() {
        return null;
    }

    /**
     * get the global people maximums
     *
     * @return array
     */
    public function getGlobalPeopleMaximums() {
        $config = new RM_ExcursionPricesConfig();
        return $config->getAll()->toArray();
    }

    /**
     * get the people maximums for the unit
     *
     * @param string    unit id
     * @return array
     */
    public function getPeopleMaximums($unit_id) {
        $config = new RM_UnitExcursionPricesConfig();
        $max_occupancy = $config->fetchValueByUnit($unit_id, "max_occupancy");
        $max_adults = $config->fetchValueByUnit($unit_id, "max_adults");
        $max_children = $config->fetchValueByUnit($unit_id, "max_children");
        $max_infants = $config->fetchValueByUnit($unit_id, "max_infants");

        // check if there's a saved board type and pass this back for the for initalisation
        $saveBoardSelection = $this->getSavedBoardType($unit_id);


        return array("max_occupancy" => $max_occupancy, "max_adults" => $max_adults, "max_children" => $max_children, "max_infants" => $max_infants, "saved_board" => $saveBoardSelection);
    }

    /**
     * Returns PHP dateformat to present reservation start and end date on the UI
     *
     * @param bool $php - internal PHP date format or UI date format, if true - internal PHP date format
     * @return string
     */
    public function getDateformat($php = false) {
        if ($php) {
            return RM_Config::MYSQL_DATEFORMAT_SHORT;
        }

        $config = new RM_Config();
        return $config->getJSDateformat();
    }

    /**
     * Returns unit that are not that have a min stay on this period more than this period
     * or don't have a prices at all for this period
     * 
     * @param RM_Reservation_Period $period
     * @return array array with unit ids
     */
    public function getByMinPeriod(RM_Reservation_Period $period) {
        $unitIDs = array();
        $model = new RM_UnitExcursionPrices();
        $unitIDs = $model->getByMinPeriod($period);
        return $unitIDs;
    }

    /**
     * Returns unit that are not that have a max stay on this period less than this period
     * or don't have a prices at all for this period
     *
     * @param RM_Reservation_Period $period
     * @return array array with unit ids
     */
//    public function getByMaxPeriod(RM_Reservation_Period $period){
//        $unitIDs = array();
//        $model = new RM_UniExcursionPrices();
//        $unitIDs = $model->getByMaxPeriod($period);
//        return $unitIDs;
//    }

    /**
     * Calculates total price for one unit
     *
     * @todo in this method there should be invoke 'getSavedBoardType' and add this parameter to RM_ExcursionPrices_Calculator->getTotalUnitPrice
     * @param RM_Prices_Information $information All needed data for calculate total price
     * @param bool $byStep - if true, the result will be in array (0 => array('step' => RM_Date, 'price' => float))
     * @return float Total price
     */
    public function getTotalUnitPrice(RM_Prices_Information $information, $byStep = false) {
        $calculator = new RM_ExcursionPrices_Calculator(
                        new RM_UnitExcursionPrices,
                        new RM_UnitExcursionPricesConfig,
                        RM_Environment::getInstance()->getTranslation(RM_Environment::TRANSLATE_ERRORS)
        );

        $returnValue = $calculator->getTotalUnitPrice($information, $byStep);
        return $returnValue;
    }

    /**
     * Returns the lowest price of a unit over a given period
     *
     * @param $information RM_Prices_Information - information object,
     * contains all needed information about unit reservation:
     * unit,
     * start date,
     * end date,
     * number of persons
     * etc.
     *
     * @return float
     */
    public function getLowestUnitPrice(RM_Prices_Information $information) {
        $model = new RM_UnitExcursionPrices();
        return $model->getLowestPrice($information);
    }

    /**
     * Return max prices among all units for the one default period for price manager
     * @return float
     */
    public function getTotalHighestPrice() {
        $model = new RM_UnitExcursionPrices();
        return $model->getHighestPrice();
    }

    /**
     * Returns all unit ids that have price in price range in input period
     *
     * @param float $from
     * @param float $to
     * @param RM_Reservation_Period $period
     * @return array array with unit ids
     */
    public function getByPriceRange($from, $to, RM_Reservation_Period $period = null) {
        $model = new RM_UnitExcursionPrices();
        $rows = $model->getByPriceRange($from, $to, $period);

        $unitIDs = array();
        foreach ($rows as $row) {
            $unitIDs[] = $row->unit_id;
        }

        //TODO: here you need to add a code to unique unit_id cause there
        // could be different rows with the different board types
        // for the same unit for the same period.
        return $unitIDs;
    }

    /**
     * this method returns if the times should be collected for this price module
     *
     * @return boolean
     */
    public function getShowTime(){
        return 0;
    }

    /**
     * returns the saved selected board type (b&b, sc, hb, fb, ai)
     *
     * @todo this method should be protected or private
     * @param string $unit_id   unit id
     * @deprecated
     */
    public function getSavedBoardType($unit_id){
        if (!$unit_id) return;

        if (isset($_SESSION['Excursion_prices_board'])){
            if ((int)$_SESSION['Excursion_prices_board']['unit_id']==(int)$unit_id){
                return $_SESSION['Excursion_prices_board']['value'];
            }
        }
        return; 
    }

    /**
     * Returns the other information associated with this price system.
     *
     * @return array
     */
    public function getOtherInfo(){
        return array("k"=>"board_type");
    }

    public function getBoardTypes($unitID,$period){
        $priceObj = new RM_UnitExcursionPrices();
        $boardTypes = $priceObj->getBoardTypes($unitID,$period)->toArray();

        return $boardTypes;
    }

    /**
     * returns uits that have the availability check disabled.
     * @return <type>
     */
    public function getUnitWithAvailabiltyCheckDisabled(){
        $model = new RM_UnitExcursionPricesConfig();
        $rows = $model->fetchUnitsByValue('availablity_check');

        $unitIDs = array();
        foreach ($rows as $row) {
            if ($row->value=="0"){
                $unitIDs[] = (array("id"=>$row->unit_id));
            }
        }
        return $unitIDs;
    }

}